package ldk.xposed.dexreplace

import android.app.Instrumentation
import android.content.Context
import android.content.pm.ApplicationInfo
import android.os.Process
import android.util.Log
import dalvik.system.PathClassLoader
import de.robv.android.xposed.*
import de.robv.android.xposed.callbacks.XC_LoadPackage
import ldk.xposed.dexreplace.classloaders.MiddleClassLoader
import java.io.File

/**
 * Created by liangdengke on 2018/4/26.
 */
class HookLoadedPackage: IXposedHookLoadPackage {
    override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
        if (lpparam.appInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0)
            return

        try {
            val server = Server(null)
            val replaceInfo = server.parseReplaceInfo(lpparam.packageName)
            XposedBridge.log("handlePackage: ${lpparam.packageName}, and replaceInfo: $replaceInfo")
            if (replaceInfo != null){
                XposedBridge.log("准备替换DexInfo: ${lpparam.packageName} =====> $replaceInfo")
                XposedHelpers.findAndHookMethod(Instrumentation::class.java,
                        "newApplication", ClassLoader::class.java, String::class.java, Context::class.java,
                        object : XC_MethodReplacement(){
                            override fun replaceHookedMethod(param: MethodHookParam): Any {
                                val context = param.args[2] as Context
                                val className = param.args[1] as String

                                val dexFile = File(replaceInfo.dexFilePath)
                                if (dexFile.exists() && dexFile.canRead()){
                                    XposedBridge.log("after install dex")
                                    val pathClassLoader = context.classLoader as PathClassLoader
                                    val parent = pathClassLoader.parent
                                    val myClassLoader = MiddleClassLoader(replaceInfo.dexFilePath, parent, pathClassLoader)
                                    XposedHelpers.setObjectField(pathClassLoader, "parent", myClassLoader)
                                }else{
                                    XposedBridge.log("没有权限或者没有文件")
                                }
                                return Instrumentation.newApplication(context.classLoader.loadClass(className), context)
                            }
                        })
            }
        }catch (e: Exception){
            Log.e("DexReplace", e.message, e)
        }
    }
}
